package com.threeox.ormlibrary.util;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;

import com.alibaba.fastjson.JSONObject;
import com.threeox.ormlibrary.annotation.AddColumn;
import com.threeox.ormlibrary.annotation.AlterTable;
import com.threeox.ormlibrary.annotation.create.Column;
import com.threeox.ormlibrary.annotation.create.Primary;
import com.threeox.ormlibrary.annotation.create.Table;
import com.threeox.ormlibrary.db.OrmSQLDataBaseDao;
import com.threeox.ormlibrary.entity.ColumnType;
import com.threeox.ormlibrary.entity.TableMsg;
import com.threeox.utillibrary.util.EmptyUtils;
import com.threeox.utillibrary.util.LogUtils;
import com.threeox.utillibrary.util.java.JAVAUtil;

import java.lang.reflect.Field;
import java.util.List;

/**
 *
 * @ClassName: TableUtil
 *
 * @Description: (表的工具类)
 *
 * @author 赵屈犇
 *
 * @date 创建时间:2016/12/16 15:49
 *
 * @version 1.0
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class TableUtil {

	private final String TAG = "TableUtil";
	private Context mContext = null;
	private SQLiteDatabase db = null;
	private List<Class> packClasses;
	private List<Class> alertPackClasses;

	public static TableUtil getInstance(Context context, SQLiteDatabase db, String... packNames) {
		return new TableUtil(context, db, packNames);
	}

	private TableUtil(Context context, SQLiteDatabase db, String... packNames) {
		this.db = db;
		this.mContext = context;
		JAVAUtil javaUtil = JAVAUtil.getInstance(mContext);
		this.packClasses = javaUtil.getClazzByPackage(Table.class, packNames);
		this.alertPackClasses = javaUtil.getClazzByPackage(AlterTable.class, packNames);
	}

	/**
	 * 创建表
	 */
	public TableUtil createTable() {
		if (EmptyUtils.isEmpty(packClasses))
			return this;
		db.beginTransaction();
		try {
			for (Class packClass : packClasses) {
				Table clazz = (Table) packClass.getAnnotation(Table.class);
				String value = clazz.value();
				StringBuffer createSql = new StringBuffer("CREATE TABLE IF NOT EXISTS " + (EmptyUtils.isNotEmpty(value) ? value : packClass.getSimpleName()) + "(");
				String sql = getColumnSql(createSql, packClass);
				sql += "\n);";
				db.execSQL(sql);
				LogUtils.d(TAG, sql);
			}
			db.setTransactionSuccessful();
		} catch (Exception e) {
			LogUtils.e(TAG, e.getMessage());
		} finally {
			db.endTransaction();
		}
		return this;
	}

    /**
     * 修改表
     *
     * @param oldVersion
     * @return
     */
	public TableUtil alterTable(int oldVersion){
        if (EmptyUtils.isEmpty(alertPackClasses)) {
            return this;
        }
        db.beginTransaction();
        try {
            for (Class packClass : alertPackClasses) {
                AlterTable clazz = (AlterTable) packClass.getAnnotation(AlterTable.class);
                if (oldVersion == clazz.version()) {
                    StringBuffer sql = new StringBuffer();
                    String newTableName = clazz.newTableName();
                    String oldTableName = clazz.oldTableName();
                    if (EmptyUtils.isNotEmpty(oldTableName) && EmptyUtils.isNotEmpty(newTableName)) {
                        sql.append("ALTER TABLE " + oldTableName + " RENAME TO " + newTableName + ";\n");

                    }
                    getAddColumn(sql, packClass, EmptyUtils.isNotEmpty(newTableName) ? newTableName : oldTableName);
                    db.execSQL(sql.toString());
                }
            }
            db.setTransactionSuccessful();
        } catch (Exception e) {
            LogUtils.e(TAG, e.getMessage());
        } finally {
            db.endTransaction();
        }
        return this;
	}

    public String getAddColumn(StringBuffer sql, Class clazz, String tableName) {
        Field[] fields = clazz.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			boolean isColumn = field.isAnnotationPresent(AddColumn.class);
			if (!isColumn) continue;
            AddColumn column = field.getAnnotation(AddColumn.class);
            String columnName = column.columnName();
            StringBuffer colSql = new StringBuffer("ALTER TABLE " + tableName + " ADD COLUMN " + (EmptyUtils.isNotEmpty(columnName) ? columnName : field.getName()));
            colSql.append(getColumnType(field, column.columnType(), column.length()));
            if (column.isPrimary())
                colSql.append(" PRIMARY KEY");
            if (column.isAutoIncrement())
                colSql.append(" AUTOINCREMENT");
            if (column.isNotNull())
                colSql.append(" NOT NULL");
            if (column.isUnique())
                colSql.append(" UNIQUE");
            colSql.append(EmptyUtils.isNotEmpty(column.check()) ? " CHECK (" + column.check()+")" : "");
            colSql.append((EmptyUtils.isNotEmpty(column.defaultVal()) ? " DEFAULT " + column.defaultVal() : "" ) + ";\n");
            sql.append(colSql);
		}
        // 加载父类的变量
        Class superClazz = clazz.getSuperclass();
        if (superClazz != null) {
            getAddColumn(sql, superClazz, tableName);
        }
		return sql.toString();
	}

	/**
	 * 得到列的Sql
	 *
	 * @param sql
	 * @param clazz
	 * @return
	 */
	private String getColumnSql(StringBuffer sql, Class clazz){
		Field[] fields = clazz.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			String primarySql = getPrimarySql(field);
			if (EmptyUtils.isNotEmpty(primarySql)){
				sql.append(primarySql);
				continue;
			}
			boolean isColumn = field.isAnnotationPresent(Column.class);
			if (!isColumn) continue;
			Column column = field.getAnnotation(Column.class);
			String columnName = column.columnName();
			StringBuffer colSql = new StringBuffer("\n\t" + (EmptyUtils.isNotEmpty(columnName) ? columnName : field.getName()));
			colSql.append(getColumnType(field, column.columnType(), column.length()));
			if (column.isPrimary())
				colSql.append(" PRIMARY KEY");
			if (column.isAutoIncrement())
				colSql.append(" AUTOINCREMENT");
			if (column.isNotNull())
				colSql.append(" NOT NULL");
			if (column.isUnique())
				colSql.append(" UNIQUE");
			colSql.append(EmptyUtils.isNotEmpty(column.check()) ? " CHECK (" + column.check()+")" : "");
			colSql.append((EmptyUtils.isNotEmpty(column.defaultVal()) ? " DEFAULT " + column.defaultVal() : "" ) + ",");
			sql.append(colSql);
		}
		// 加载父类的变量
        Class superClazz = clazz.getSuperclass();
        if (superClazz != null) {
            getColumnSql(sql, superClazz);
        }
		if (sql.toString().endsWith(","))
			return sql.substring(0	, sql.toString().length() - 1);
		return sql.toString();
	}

	/**
	 * 得到主键自增的SQL
	 *
	 * @param field
	 * @return
	 */
	private String getPrimarySql(Field field) {
		boolean isPrimary = field.isAnnotationPresent(Primary.class);
        LogUtils.d("getColumnSql", field.getName() + "-->" + isPrimary);
        if (!isPrimary) {
            return null;
        }
		Primary primary = field.getAnnotation(Primary.class);
		StringBuffer colSql = new StringBuffer("\n\t" + (EmptyUtils.isNotEmpty(primary.columnName()) ? primary.columnName() : field.getName()));
		colSql.append(" INTEGER PRIMARY KEY AUTOINCREMENT,");
        LogUtils.d("getColumnSql", colSql.toString());
		return colSql.toString();
	}

	/**
	 * 得到类的数据类型
	 *
	 * @param field
	 * @param length
	 * @return
	 */
	private String getColumnType(Field field, String columnType, String length) {
		StringBuffer result = new StringBuffer(" ");
		if (EmptyUtils.isNotEmpty(columnType)) {
            result.append(columnType);
        } else {
            Class fieldType = field.getType();
            if (fieldType == String.class) { // 如果是String
                result.append(ColumnType.TEXT);
            } else if (fieldType == Short.class || fieldType == short.class) {
                result.append(ColumnType.SMALLINT);
            } else if (fieldType == Integer.class || fieldType == int.class) {
                result.append(ColumnType.INTEGER);
            } else if (fieldType == Long.class || fieldType == long.class) {
                result.append(ColumnType.BIGINT);
            } else if (fieldType == Boolean.class || fieldType == boolean.class) {
                result.append(ColumnType.BOOLEAN);
            } else if (fieldType == Float.class || fieldType == float.class) {
                result.append(ColumnType.FLOAT);
            } else if (fieldType == Double.class || fieldType == double.class) {
                result.append(ColumnType.DOUBLE);
            } else if (fieldType == Byte[].class || fieldType == byte[].class) {
                result.append(ColumnType.BLOB);
			} else {
                result.append(ColumnType.TEXT);
            }
        }
        if (EmptyUtils.isNotEmpty(length)) {
            result.append(" (" + length + ")");
		}
		return result.toString();
	}

	private static JSONObject mTableMsgs = null;

	/**
	 * 根据表名得到表信息
	 *
	 * @param key
	 * @return
	 */
	@Deprecated
	public synchronized static TableMsg getTableMsgByKey(String key) {
		try {
			if (mTableMsgs == null) {
				mTableMsgs = OrmSQLDataBaseDao.queryAllTableMsg();
			}
			return mTableMsgs.getObject(key, TableMsg.class);
		} catch (Exception e) {
			e.printStackTrace();
			LogUtils.e("getTableMsgByKey", "根据表名得到表信息失败:" + e.getMessage());
		}
		return null;
	}
}
